package sf.r2dbc.mapper;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import sf.core.DBObject;
import sf.r2dbc.dao.R2dbcClient;

import java.util.List;

/**
 * 通用mapper类
 * @param <T>
 */
public interface R2dbcDaoMapper<T extends DBObject> {
    /**
     * 合并记录
     * @param entity
     * @return
     */
    Mono<Integer> merge(T entity);

    /**
     * 通用插入，插入一个实体对象到数据库,返回主键
     * @param entity 实体类
     * @return 返回插入的数量
     */
    Mono<Integer> insert(T entity);


    /**
     * 批量插入实体,返回主键
     * @param list
     * @return 返回插入的总数
     */
    Flux<Integer> insertBatch(List<T> list);

    /**
     * 批量插入实体,快速插入 不返回主键
     * @param list
     * @return 返回插入的总数
     */
    Flux<Integer> insertBatchFast(List<T> list);

    /**
     * 根据主键更新对象,对象set过才被更新
     * @param entity 实体
     * @return 返回变更的总数
     */
    Mono<Integer> updateById(T entity);

    /**
     * 更新
     * @param entity
     * @return
     */
    Mono<Integer> update(T entity);

    /**
     * 批量更新
     * @param list
     * @return
     */
    Flux<Integer> updateBatch(List<T> list);

    /**
     * 删除
     * @param entity
     * @return
     */
    Mono<Integer> delete(T entity);

    /**
     * 根据主键删除对象，如果对象是复合主键，传入对象本生即可
     * @param key 主键
     * @return
     */
    Mono<Integer> deleteById(Object... key);

    /**
     * 删除
     * @param entity
     * @return
     */
    Mono<Integer> logicDelete(T entity);

    /**
     * 根据主键删除对象，如果对象是复合主键，传入对象本生即可
     * @param key 主键
     * @return
     */
    Mono<Integer> logicDeleteById(Object... key);
    /**
     * 批量删除
     * @param entities
     * @return
     */
    Flux<Integer> deleteInBatch(Iterable<T> entities);

    /**
     * 清空表
     */
    Mono<Integer> deleteAllInBatch();

    /**
     * 根据主键获取对象，如果对象不存在，返回null
     * @param keys
     * @return
     */
    Mono<T> unique(Object... keys);

    /**
     * 获取单一对象，如果对象不存在，返回null
     * @param query
     * @return
     */
    Mono<T> single(T query);

    /**
     * 获取单一对象，如果在事物中执行会添加数据库行级锁(select * from table where id = ? for
     * update)，如果对象不存在，返回null
     * @param query
     * @return
     */
    Mono<T> lock(T query);

    /**
     * 返回实体在数据库里的总数
     * @return
     */
    Mono<Long> count();

    /**
     * 根据条件查询数量
     * @param query
     * @return
     */
    Mono<Long> count(T query);

    /**
     * 是否存在,根据主键查询
     * @param id
     * @return
     */
    Mono<Boolean> existsById(Object... id);

    /**
     * 是否存在,根据对象查询
     * @param query
     * @return
     */
    Mono<Boolean> exists(T query);

    /**
     * 返回实体对应的所有数据库记录
     * @return
     */
    Flux<T> selectList(T query);

    /**
     * @return
     */
    R2dbcClient getR2dbcClient();

    /**
     * @return
     */
    Class<T> getDomainClass();
}
